iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
自我挑戰組

JavaScript 奇奇怪怪的核心觀念系列 第 3

(Day3) 執行緒與同步&非同步

  • 分享至 

  • xImage
  •  

單執行緒

JavaScript 是單執行緒的語言,而單執行緒的意思就是一次只做一件事情。

不過這樣的話 單執行緒 的 JavaScript , 一旦程式碼時遇到卡住的地方 (阻塞),整個程式碼不就是應該卡住無法使用?

就是為了解決這個問題, JS 中有部分方法是使用非同步來避免這件事。

非同步(Asynchronous)

什麼是非同步?

先來說說什麼是同步(Synchronous),同步的意思就是,當程式碼執行時他一定會依序做完才往下做,例如以下程式碼:

function Fn1(){
console.log('我第一')
}
function Fn2(){
console.log('我第二')
}
function Fn3(){
console.log('我第三')
}
Fn1() 
Fn2() 
Fn3() 

以上 console 顯示的一定會是按照順序顯示, 我第一 ⇒ 我第二 ⇒ 我第三 ,這種會按照順序執行的程式碼部分就被稱做『同步』。

理解好什麼是同步後,非同步自然比較好理解,自然就是同步的反義詞,不會依照順序執行,例如以下程式碼:

function Fn1(){
console.log('我第一')
}
function Fn2(){
setTimeout(() => {
    console.log('我第二')
  }, 0);
}
function Fn3(){
console.log('我第三')
}
Fn1()
Fn2() 
Fn3() 

這邊使用 setTimeout() 來模擬非同步語法,可發現顯示出來的順序會是, 我第一 ⇒ 我第三 ⇒ 我第二 ,之所以順序是這樣,是因為 JavaScript 有一個稱做 事件循環(event loop)的特性來處理非同步語法。

JavaScript 中常見的非同步語法有:

  • setTimeout() 及 setInterval() 定時器。
  • fetch 、 XMLHttpRequest 等等處理 Ajax 行為的語法。
  • ES6 新增的 Promise 。

事件循環 (event loop)

event loop 的作用是去監控堆疊(call stack)和工作佇列(task queue),當堆疊當中沒有執行項目的時候,便把佇列中的內容拉到堆疊中去執行。

上面引用 pjchender 大大 文章中提到的一段話,這段話個人認為,確實是最好理解事件循環的一段話,在(Day1)執行環境與執行堆疊有提到,在函示中呼叫另一個函示會造成堆疊狀況(call stack),雖然稱做堆疊,但這種狀況其實是屬於同步的狀況。

而工作佇列(task queue)則是 JavaScript 這語法專門存放非同步語法的地方。

也就是說 事件循環 特性就是,非同步語法會等待 同步語法 執行完畢接著才被執行,這邊也使用一段程式碼查看這個特性:

setTimeout(function () {
      console.log('非同步');
    }, 0);
    function test() {
      for (var i = 1; i <= 10; i++) {
        (function () {
          console.log(i)
        })()
      }
    }
    test()

呼叫 test() 這個函示會在 console 依序顯示 1、2、3 ...10 。
運行上面範例會是先顯示完 1、2、3 ...10 ,最後才顯示 非同步 的字串,如果你覺得你的電腦夠好,也可以試者把 for 迴圈改成執行 10 萬次,結果也會是非同步字串最後才顯示。

參考文獻


上一篇
(Day2) 範圍鍊與提升
下一篇
(Day4) 陳述式 /表達式
系列文
JavaScript 奇奇怪怪的核心觀念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言